/*
 * DemonstratorFrame.java
 *
 * Created on 9 de Julho de 2011, 13:46
 */

package intopo.demonstrator.partnerclassification.gui;

import intopo.demonstrator.partnerclassification.Parameters;
import intopo.demonstrator.partnerclassification.State;
import intopo.demonstrator.partnerclassification.Statistics;

import java.util.Timer;

/**
 *
 * @author  pedro
 */
public class DemonstratorFrame
	extends javax.swing.JFrame
{
//	/**
//	 * Single parameters used by the components in this package.
//	 */
//	static final Parameters parameters = new Parameters ();
//	private State currentState;
//	private Statistics statistics;
	final private RawDataTableModel rawDataTableModel;
	/**
	 * The current timer.
	 */
	private Timer timer;
	/** Creates new form DemonstratorFrame */
	public DemonstratorFrame ()
	{
		rawDataTableModel = new RawDataTableModel ();
		initComponents ();
		timer = null;
	}
	/**
	 * Initialise data and components after parameters have been changed or the model must be restarted.
	 */
	private void parametersChanged ()
	{
		Model.parametersChanged ();
		this.weightHistoryComponent.parametersChanged ();
		this.probabilityCombinationVectorsHistoryComponent.parametersChanged ();
		this.gamesPlayedComponent.parametersChanged ();
		this.rawDataTableModel.fireTableStructureChanged ();
	}
	private void newTransition ()
	{
		Model.newTransition ();
		this.weightHistoryComponent.newTransition ();
		this.probabilityCombinationVectorsHistoryComponent.newTransition ();
		this.gamesPlayedComponent.newTransition ();
		this.rawDataTableModel.fireTableRowsInserted (Model.history.size () - 1, Model.history.size () - 1);
	}
	/** This method is called from within the constructor to
	 * initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is
	 * always regenerated by the Form Editor.
	 */
   // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
   private void initComponents() {
      javax.swing.JPanel controlPanel;
      javax.swing.JPanel footerPanel;
      javax.swing.JSplitPane modelStatisticsSplitPane1;
      javax.swing.JSplitPane modelStatisticsSplitPane2;
      javax.swing.JScrollPane rawDataScrollPane;

      modelParametersComponent = new ModelParametersComponent ();
      footerPanel = new javax.swing.JPanel();
      controlPanel = new javax.swing.JPanel();
      resetButton = new javax.swing.JButton();
      runButton = new javax.swing.JButton();
      stopButton = new javax.swing.JButton();
      nextButton = new javax.swing.JButton();
      messageLabel = new javax.swing.JLabel();
      dataTabbedPane = new javax.swing.JTabbedPane();
      modelStatisticsSplitPane1 = new javax.swing.JSplitPane();
      modelStatisticsSplitPane2 = new javax.swing.JSplitPane();
      weightHistoryComponent = new WeightHistoryComponent ();
      probabilityCombinationVectorsHistoryComponent = new intopo.demonstrator.partnerclassification.gui.ProbabilityCombinationVectorsHistoryComponent();
      gamesPlayedComponent = new intopo.demonstrator.partnerclassification.gui.GamesPlayedComponent();
      rawDataScrollPane = new javax.swing.JScrollPane();
      rawDataTable = new javax.swing.JTable();

      setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
      setTitle("Demonstrator Partner Classification Algorithm");
      modelParametersComponent.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
         public void propertyChange(java.beans.PropertyChangeEvent evt) {
            modelParametersComponentPropertyChange(evt);
         }
      });

      getContentPane().add(modelParametersComponent, java.awt.BorderLayout.WEST);

      footerPanel.setLayout(new java.awt.BorderLayout());

      resetButton.setText("Reset");
      resetButton.addActionListener(new java.awt.event.ActionListener() {
         public void actionPerformed(java.awt.event.ActionEvent evt) {
            resetButtonActionPerformed(evt);
         }
      });

      controlPanel.add(resetButton);

      runButton.setText("Run");
      runButton.addActionListener(new java.awt.event.ActionListener() {
         public void actionPerformed(java.awt.event.ActionEvent evt) {
            runButtonActionPerformed(evt);
         }
      });

      controlPanel.add(runButton);

      stopButton.setText("Stop");
      stopButton.setEnabled(false);
      stopButton.addActionListener(new java.awt.event.ActionListener() {
         public void actionPerformed(java.awt.event.ActionEvent evt) {
            stopButtonActionPerformed(evt);
         }
      });

      controlPanel.add(stopButton);

      nextButton.setText("Next");
      nextButton.addActionListener(new java.awt.event.ActionListener() {
         public void actionPerformed(java.awt.event.ActionEvent evt) {
            nextButtonActionPerformed(evt);
         }
      });

      controlPanel.add(nextButton);

      footerPanel.add(controlPanel, java.awt.BorderLayout.CENTER);

      footerPanel.add(messageLabel, java.awt.BorderLayout.SOUTH);

      getContentPane().add(footerPanel, java.awt.BorderLayout.SOUTH);

      modelStatisticsSplitPane2.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
      modelStatisticsSplitPane2.setLeftComponent(weightHistoryComponent);

      modelStatisticsSplitPane2.setRightComponent(probabilityCombinationVectorsHistoryComponent);

      modelStatisticsSplitPane1.setLeftComponent(modelStatisticsSplitPane2);

      modelStatisticsSplitPane1.setRightComponent(gamesPlayedComponent);

      dataTabbedPane.addTab("Plots", modelStatisticsSplitPane1);

      rawDataTable.setModel(rawDataTableModel);
      rawDataScrollPane.setViewportView(rawDataTable);

      dataTabbedPane.addTab("Raw Data", rawDataScrollPane);

      getContentPane().add(dataTabbedPane, java.awt.BorderLayout.CENTER);

      pack();
   }// </editor-fold>//GEN-END:initComponents

	private void stopButtonActionPerformed (java.awt.event.ActionEvent evt) {//GEN-FIRST:event_stopButtonActionPerformed
		this.timer.cancel ();
		this.timer = null;
		this.stopButton.setEnabled (false);
		this.runButton.setEnabled (true);
		this.nextButton.setEnabled (true);
		this.resetButton.setEnabled (true);
	}//GEN-LAST:event_stopButtonActionPerformed

	private void runButtonActionPerformed (java.awt.event.ActionEvent evt) {//GEN-FIRST:event_runButtonActionPerformed
		this.timer = new Timer ();
		this.timer.schedule (new Walk (), 0, 70);
		this.stopButton.setEnabled (true);
		this.runButton.setEnabled (false);
		this.nextButton.setEnabled (false);
		this.resetButton.setEnabled (false);
	}//GEN-LAST:event_runButtonActionPerformed

	private void resetButtonActionPerformed (java.awt.event.ActionEvent evt) {//GEN-FIRST:event_resetButtonActionPerformed
		this.parametersChanged ();
	}//GEN-LAST:event_resetButtonActionPerformed

	private void modelParametersComponentPropertyChange (java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_modelParametersComponentPropertyChange
		if (evt.getPropertyName () == ModelParametersComponent.PARAMETERS_PROPERTY) {
			this.parametersChanged ();
		}
	}//GEN-LAST:event_modelParametersComponentPropertyChange

	private void nextButtonActionPerformed (java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nextButtonActionPerformed
		this.newTransition ();
	}//GEN-LAST:event_nextButtonActionPerformed
	
	/**
	 * @param args the command line arguments
	 */
	public static void main (String args[]) {
		java.awt.EventQueue.invokeLater (new Runnable () {
			public void run () {
				new DemonstratorFrame ().setVisible (true);
			}
		});
	}
	
   // Variables declaration - do not modify//GEN-BEGIN:variables
   private javax.swing.JTabbedPane dataTabbedPane;
   private intopo.demonstrator.partnerclassification.gui.GamesPlayedComponent gamesPlayedComponent;
   private javax.swing.JLabel messageLabel;
   private intopo.demonstrator.partnerclassification.gui.ModelParametersComponent modelParametersComponent;
   private javax.swing.JButton nextButton;
   private intopo.demonstrator.partnerclassification.gui.ProbabilityCombinationVectorsHistoryComponent probabilityCombinationVectorsHistoryComponent;
   private javax.swing.JTable rawDataTable;
   private javax.swing.JButton resetButton;
   private javax.swing.JButton runButton;
   private javax.swing.JButton stopButton;
   private intopo.demonstrator.partnerclassification.gui.WeightHistoryComponent weightHistoryComponent;
   // End of variables declaration//GEN-END:variables

	/**
	 * This class is responsible for running the partner classification model.
	 */
	final class Walk
		extends java.util.TimerTask
	{
		public void run ()
		{
			newTransition ();
		}
	}
	
	final static class RawDataTableModel
		extends javax.swing.table.AbstractTableModel
	{
		public int getColumnCount ()
		{
			return Model.parameters.getPartners ().size () + 2 * Model.parameters.getPoolSize ();
		}
		public int getRowCount ()
		{
			return Model.history.size ();
		}
		public boolean isCellEditable (int row, int column)
		{
			return false;
		}
		public Object getValueAt (int row, int column)
		{
			final int poolSize = Model.parameters.getPoolSize ();
			State state = Model.getHistory (row);
			if (column < poolSize) {
				return Integer.toString (state.getRawProbability (column));
			}
			else if (column < 2 * poolSize) {
				int index = column - poolSize;
				if (index == state.getSelectedCombination ()) {
					return "* " + state.getCombination (index).ids ();
				}
				else {
					return "  " + state.getCombination (index).ids ();
				}
			}
			else {
				return Short.toString (state.getRawWeight (Model.partners [column - 2 * poolSize]));
			}
		}
		public Class<?> getColumnClass (int column)
		{
			if (column < Model.parameters.getPoolSize ()) {
				return Integer.class;
			}
			else if (column < 2 * Model.parameters.getPoolSize ()) {
				return String.class;
			}
			else {
				return Short.class;
			}
		}
		public String getColumnName (int column)
		{
			final int poolSize = Model.parameters.getPoolSize ();
			if (column < poolSize) {
				return String.format ("p%d", column);
			}
			else if (column < 2 * poolSize) {
				return String.format ("c%d", column - poolSize);
			}
			else {
				return String.format ("w%d %s", column - 2 * poolSize, Model.partners [column - 2 * poolSize].getBehaveAcceptablyProbability ().toString ());
			}
		}
	}
}

